from django.db import transaction
from rest_framework import serializers
from sku.models import Sku
from order.models import Order,OrderStockLock,physical_distribution_history
from rest_framework.exceptions import ValidationError
from sku.serializer import SkuSerializer,singleSkuSerializer
class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = ['id','num','sku','actual_payment','order_number','delivery_time','remark','address','parent_order']
        extra_kwargs = {
            'id':{
                'read_only':True
            },
            'order_number':{
                'read_only':True
            },
            'actual_payment':{
               'read_only':True
            },
            'remark':{
                'required':False,
                'allow_null':True
            },
            'delivery_time':{
                'required':False,
                'allow_null':True
            },
        }
    def validate(self, data):
        num = int(data['num'])
        # ModelSerializer会根据模型字段自动生成对应的序列化器字段
        # 假设Order模型中的sku字段是一个外键指向Sku模型，那么在序列化器中，
        # DRF会自动将这个字段处理为PrimaryKeyRelatedField。
        # 这意味着当客户端发送sku的ID时，序列化器会将其转换为对应的Sku实例。
        skuObj=data['sku']
        print('sku获取')
        print(skuObj)
        addressObj=data['address']
        order_number=self.context['order_number']
        if not addressObj:
            raise ValidationError("地址不存在")
        if num < 0:
            raise ValidationError("数量不能小于0")
        if num>skuObj.stock:
            raise ValidationError("库存不足")
        actual_payment=self.get_actual_payment(skuObj,num)
        data['actual_payment']=actual_payment
        data['user']=self.context['user']
        data['order_goods_id']=skuObj.product.id
        data['order_number']=order_number
        return data
    # 获得各个sku的实际支付金额
    def get_actual_payment(self,skuObj,num):
        print(type(skuObj.price))
        actual_payment = skuObj.price * num
        freight_price=skuObj.freight*num
        actual_payment=actual_payment+freight_price
        return actual_payment

    def create(self, validated_data):
        with transaction.atomic():
            orderObj=Order.objects.create(**validated_data)
            orderObj.save()
            # 锁定库存
            self.lock_stock(orderObj.sku.id,orderObj.num,orderObj.order_number)
            return orderObj
    def lock_stock(self,sku_id, quantity, order_no):
        with transaction.atomic():
            # select_for_update()
            # 是用于在数据库查询时锁定所选行，直到事务结束。这通常用在事务块中，
            # 防止其他事务修改或锁定同一行，避免竞态条件。
            sku = Sku.objects.select_for_update().get(pk=sku_id)
            if sku.stock - sku.frozen_stock < quantity:
                raise ValidationError("库存不足")
            # 创建锁定记录
            OrderStockLock.objects.create(
                sku=sku,
                order_no=order_no,
                quantity=quantity
            )
            # 更新冻结库存
            sku.frozen_stock += quantity
            sku.save(update_fields=['frozen_stock'])


class physicalDistributionHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = physical_distribution_history
        fields = '__all__'


class OrderInfoSerializer(serializers.ModelSerializer):
    actual_payment=serializers.SerializerMethodField()
    sku_info=serializers.SerializerMethodField()
    phy=serializers.SerializerMethodField()
    goods_name=serializers.SerializerMethodField()
    son_orders=serializers.SerializerMethodField()
    class Meta:
        model = Order
        fields = ['id','num','sku','actual_payment','order_number','delivery_time','remark','address','sku_info','phy','order_of_payment',"freight","delivery_company","created_time","goods_name",'son_orders']
    def _get_sku_obj(self,obj):
        skuid=obj.sku.id
        skuObj=Sku.objects.get(pk=skuid)
        if not skuObj:
            raise ValidationError("sku不存在")
        return skuObj
    def get_actual_payment(self,obj):
        actual_payment = self._get_sku_obj(obj).price * obj.num
        freight_price = self._get_sku_obj(obj).freight * obj.num
        actual_payment = actual_payment + freight_price
        return actual_payment
    def get_sku_info(self,obj):
        sku_ser=singleSkuSerializer(instance=self._get_sku_obj(obj))
        return sku_ser.data
    def get_freight(self,obj):
        return self._get_sku_obj(obj).freight
    def get_phy(self,obj):
        queryset=physical_distribution_history.objects.filter(order=obj).order_by('-time')
        ser=physicalDistributionHistorySerializer(instance=queryset,many=True)
        return ser.data
    def get_goods_name(self,obj):
        return self._get_sku_obj(obj).product.name

    def get_son_orders(self, obj):
        """序列化同一订单号下的多个商品项"""
        son_orders = Order.objects.filter(parent_order=obj)
        print(son_orders)
        serializer = self.__class__(son_orders, many=True)
        return serializer.data

